package com.yeskery.nut.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * JDK动态代理工厂
 * @author sprout
 * @version 1.0
 * 2022-08-28 12:19
 */
public class JdkProxyObjectFactory implements ProxyObjectFactory{

    /**
     * 拦截处理对象
     */
    private final WrapInvocationHandler wrapInvocationHandler;

    /**
     * 构建JDK动态代理工厂对象
     * @param wrapInvocationHandler 拦截处理对象
     */
    public JdkProxyObjectFactory(WrapInvocationHandler wrapInvocationHandler) {
        if (wrapInvocationHandler == null) {
            throw new ProxyObjectCreateException("JDK Proxy InvocationHandler Must Not Be Null.");
        }
        this.wrapInvocationHandler = wrapInvocationHandler;
    }

    @Override
    public Object createProxyInstance(Class<?> clazz) {
        Class<?>[] interfaces;
        if (clazz.isInterface()) {
            List<Class<?>> classes = Arrays.stream(clazz.getInterfaces()).collect(Collectors.toList());
            if (clazz.isInterface()) {
                classes.add(clazz);
            }
            interfaces = classes.toArray(new Class[0]);
        } else {
            interfaces = clazz.getInterfaces();
        }

        return Proxy.newProxyInstance(this.getClass().getClassLoader(), interfaces, new JdkInvocationHandlerAdapter());
    }

    @Override
    public Object createProxyInstance(Class<?> clazz, Class<?>[] argumentTypes, Object[] arguments) {
        throw new ProxyObjectCreateException("JDK Proxy Only Support Interface.");
    }

    /**
     * JDK动态代理拦截处理适配器
     * @author sprout
     * @version 1.0
     * 2022-08-28 14:48
     */
    private class JdkInvocationHandlerAdapter implements InvocationHandler {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return wrapInvocationHandler.invoke(proxy, method, args);
        }
    }
}
